home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 19 / Amiga Plus Leser CD 19.iso / Tools / Development / qstat25b / hcache.c < prev    next >
C/C++ Source or Header  |  2002-11-18  |  10KB  |  449 lines

  1. /*
  2.  * qstat 2.4
  3.  * by Steve Jankowski
  4.  * steve@activesw.com
  5.  * http://www.activesw.com/people/steve/qstat.html
  6.  *
  7.  * Thanks to Per Hammer for the OS/2 patches (per@mindbend.demon.co.uk)
  8.  * Thanks to John Ross Hunt for the OpenVMS Alpha patches (bigboote@ais.net)
  9.  * Thanks to Scott MacFiggen for the quicksort code (smf@activesw.com)
  10.  *
  11.  * Inspired by QuakePing by Len Norton
  12.  *
  13.  * Copyright 1996,1997,1998,1999 by Steve Jankowski
  14.  *
  15.  * Licensed under the Artistic License, see LICENSE.txt for license terms
  16.  */
  17.  
  18.  
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <ctype.h>
  22. #include <string.h>
  23. #include <errno.h>
  24.  
  25. #include "qstat.h"
  26.  
  27. #ifdef _ISUNIX
  28. #include <sys/types.h>
  29. #include <sys/socket.h>
  30. #include <netinet/in.h>
  31. #include <arpa/inet.h>
  32. #include <netdb.h>
  33. #endif
  34.  
  35. #ifdef _WIN32
  36. #include <winsock.h>
  37. #endif
  38.  
  39. #ifdef __hpux
  40. #define STATIC static
  41. #else
  42. #define STATIC
  43. #endif
  44.  
  45. #ifndef INADDR_NONE
  46. #define INADDR_NONE ~0
  47. #endif
  48.  
  49.  
  50. typedef struct _cache_entry {
  51.     unsigned long ipaddr;
  52.     char *hostname[5];
  53. } cache_entry;
  54.  
  55. static cache_entry *hcache;
  56. static int n_entry;
  57. static int max_entry;
  58. static char *last_filename;
  59. static int n_changes;
  60. static int debug;
  61.  
  62. static void write_file(FILE *file);
  63. static cache_entry * init_entry( unsigned long ipaddr, char *hostname,
  64.     cache_entry *known);
  65. static cache_entry * find_entry( unsigned long ipaddr);
  66. static void free_entry(  cache_entry *entry);
  67. static cache_entry * validate_entry( cache_entry *entry);
  68. static cache_entry * find_host_entry( char *hostname);
  69. static void add_hostname( cache_entry *entry, const char *hostname);
  70.  
  71. int
  72. hcache_open( char *filename, int update)
  73. {
  74.     FILE *file;
  75.     char line[500], ipstr[500], hostname[500];
  76.     char *l;
  77.     int line_no, end;
  78.     unsigned long ip1, ip2, ip3, ip4, ipaddr;
  79.     cache_entry *entry;
  80.  
  81.     file= fopen( filename, update?"r+":"r");
  82.     if ( file == NULL)  {
  83.     if ( errno == ENOENT)  {
  84.         fprintf( stderr, "Creating new host cache \"%s\"\n", filename);
  85.         last_filename= filename;
  86.         return 0;
  87.     }
  88.     perror( filename);
  89.     return -1;
  90.     }
  91.     last_filename= filename;
  92.  
  93.     for ( line_no= 1; fgets( line, sizeof(line), file) != NULL; line_no++)  {
  94.     if ( strlen(line) < 2)
  95.         continue;
  96.     if ( line[strlen(line)-1] != '\n')  {
  97.         printf( "%d: line too long\n", line_no);
  98.         continue;
  99.     }
  100.     l= line;
  101.     while ( isspace( *l)) l++;
  102.     if ( *l == '#' || *l == '\0')
  103.         continue;
  104.     if ( sscanf( l, "%s%n", ipstr, &end) != 1)  {
  105.         printf( "%d: parse error\n", line_no);
  106.         continue;
  107.     }
  108.     if ( sscanf( ipstr, "%u.%u.%u.%u", &ip1, &ip2, &ip3, &ip4) != 4)  {
  109.         init_entry( 0, ipstr, NULL);
  110.         continue;
  111.     }
  112.  
  113.     if ( (ip1&0xffffff00) || (ip2&0xffffff00) ||
  114.         (ip3&0xffffff00) || (ip4&0xffffff00))  {
  115.         printf( "%d: invalid IP address \"%s\"\n", line_no, ipstr);
  116.         continue;
  117.     }
  118.      ipaddr= (ip1<<24) | (ip2<<16) | (ip3<<8) | ip4;
  119.  
  120.     entry= init_entry( ipaddr, NULL, NULL);
  121.     while ( 1)  {
  122.         l+= end;
  123.         while ( isspace( *l)) l++;
  124.         if ( *l == '#' || *l == '\0')
  125.         break;
  126.         hostname[0]= '\0';
  127.         if ( sscanf( l, "%s%n", hostname, &end) != 1)  {
  128.         printf( "%d: parse error\n", line_no);
  129.         continue;
  130.         }
  131.         init_entry( ipaddr, hostname, entry);
  132.     }
  133.     }
  134.     fclose(file);
  135.     return 0;
  136. }
  137.  
  138. STATIC cache_entry *
  139. init_entry( unsigned long ipaddr, char *hostname, cache_entry *known)
  140. {
  141.     cache_entry *entry;
  142.     int e= 0, h;
  143.     if ( n_entry == max_entry)  {
  144.     if ( max_entry == 0)  {
  145.         max_entry= 50;
  146.         hcache= (cache_entry*) malloc(sizeof(cache_entry) * max_entry * 2);
  147.     }
  148.     else  {
  149.         hcache= (cache_entry*) realloc( hcache,
  150.         sizeof(cache_entry) * max_entry * 2);
  151.     }
  152.     memset( hcache+n_entry, 0, sizeof(cache_entry) * max_entry *
  153.         (n_entry==0?2:1));
  154.     max_entry*= 2;
  155.     }
  156.  
  157.     if ( ipaddr == 0)  {
  158.     entry= find_host_entry( hostname);
  159.     if ( entry == NULL)  {
  160.         hcache[n_entry].hostname[0]= strdup( hostname);
  161.         return &hcache[n_entry++];
  162.     }
  163.     return entry;
  164.     }
  165.  
  166.     if ( known != NULL)
  167.     entry= known;
  168.     else  {
  169.     for ( e= 0; e < n_entry; e++)
  170.         if ( hcache[e].ipaddr == ipaddr)
  171.             break;
  172.     entry= &hcache[e];
  173.     entry->ipaddr= ipaddr;
  174.     }
  175.  
  176.     if ( hostname && hostname[0] != '\0')  {
  177.     for ( h= 0; h < 5; h++)
  178.         if ( entry->hostname[h] == NULL)  {
  179.         entry->hostname[h]= strdup( hostname);
  180.         break;
  181.         }
  182.     }
  183.     if ( e == n_entry)
  184.     n_entry++;
  185.     return entry;
  186. }
  187.  
  188. STATIC cache_entry *
  189. find_host_entry( char *hostname)
  190. {
  191.     cache_entry *entry= &hcache[0];
  192.     char **ehost;
  193.     int e, h;
  194.     char first= *hostname;
  195.     for ( e= 0; e < n_entry; e++, entry++)  {
  196.     ehost= &entry->hostname[0];
  197.     for ( h= 0; h < 5; h++, ehost++)
  198.         if ( *ehost && first == **ehost && strcmp( hostname, *ehost) == 0)
  199.         return entry;
  200.     }
  201.     return NULL;
  202. }
  203.  
  204. void
  205. hcache_write_file( char *filename)
  206. {
  207.     FILE *file;
  208.     if ( filename != NULL)
  209.     file= fopen( filename, "w");
  210.     else
  211.     file= stdout;
  212.     if ( file == NULL)  {
  213.     perror( filename);
  214.     return;
  215.     }
  216.     write_file( file);
  217. }
  218.  
  219. void
  220. hcache_update_file()
  221. {
  222.     FILE *file;
  223.     if ( last_filename == NULL || n_changes == 0)
  224.     return;
  225.  
  226.     file= fopen( last_filename, "w");
  227.     if ( file == NULL)  {
  228.     perror( last_filename);
  229.     return;
  230.     }
  231.     write_file( file);
  232. }
  233.  
  234. STATIC void
  235. write_file( FILE *file)
  236. {
  237.     int e, h;
  238.     for ( e= 0; e < n_entry; e++)  {
  239.     unsigned long ipaddr= hcache[e].ipaddr;
  240.     if ( ipaddr == 0)
  241.         continue;
  242.     fprintf( file, "%u.%u.%u.%u", (ipaddr&0xff000000)>>24,
  243.         (ipaddr&0xff0000)>>16, (ipaddr&0xff00)>>8, ipaddr&0xff);
  244.     if ( hcache[e].hostname[0])  {
  245.         for ( h= 0; h < 5; h++)
  246.         if ( hcache[e].hostname[h] != NULL)
  247.             fprintf( file, "%c%s", h?' ':'\t', hcache[e].hostname[h]);
  248.     }
  249.     fprintf( file, "\n");
  250.     }
  251.     fclose( file);
  252. }
  253.  
  254. void
  255. hcache_invalidate()
  256. {
  257.     int e, h;
  258.     for ( e= 0; e < n_entry; e++)
  259.     if ( hcache[e].ipaddr != 0)
  260.         memset( & hcache[e].hostname[0], 0, sizeof( hcache[e].hostname));
  261. }
  262.  
  263. void
  264. hcache_validate()
  265. {
  266.     int e, h;
  267.     char **alias;
  268.     struct hostent *ent;
  269.     unsigned long ipaddr;
  270.     cache_entry *entry;
  271.  
  272.     for ( e= 0; e < n_entry; e++)  {
  273.     fprintf( stderr, "\r%d / %d  validating ", e, n_entry);
  274.     if ( hcache[e].ipaddr != 0)  {
  275.         ipaddr= hcache[e].ipaddr;
  276.         fprintf( stderr, "%u.%u.%u.%u", (ipaddr&0xff000000)>>24,
  277.         (ipaddr&0xff0000)>>16, (ipaddr&0xff00)>>8, ipaddr&0xff);
  278.         ipaddr= htonl( ipaddr);
  279.         ent= gethostbyaddr( (char*)&ipaddr, sizeof(unsigned long),
  280.         AF_INET);
  281.     }
  282.     else if ( hcache[e].hostname[0] != NULL)  {
  283.         fprintf( stderr, "%s", hcache[e].hostname[0]);
  284.         ent= gethostbyname( hcache[e].hostname[0]);
  285.         if ( ent != NULL)  {
  286.         memcpy( &ipaddr, ent->h_addr_list[0], sizeof(ipaddr));
  287.         ipaddr= ntohl( ipaddr);
  288.         if ( (entry= find_entry( ipaddr)) != NULL)  {
  289.             add_hostname( entry, hcache[e].hostname[0]);
  290.             free_entry( &hcache[e]);
  291.         }
  292.         else
  293.             hcache[e].ipaddr= ipaddr;
  294.         }
  295.     }
  296.     else
  297.         continue;
  298.     if ( ent == NULL)
  299.         continue;
  300.  
  301.     if ( ent->h_name && ent->h_name[0] != '\0')
  302.         add_hostname( &hcache[e], ent->h_name);
  303.     printf( "h_name %s\n", ent->h_name?ent->h_name:"NULL");
  304.     alias= ent->h_aliases;
  305.     while ( *alias)  {
  306.         add_hostname( &hcache[e], *alias);
  307.         printf( "h_aliases %s\n", *alias);
  308.         alias++;
  309.     }
  310.     }
  311. }
  312.  
  313. STATIC cache_entry *
  314. validate_entry( cache_entry *entry)
  315. {
  316.     struct hostent *ent;
  317.     char **alias;
  318.     cache_entry *tmp;
  319.     unsigned long ipaddr;
  320.  
  321.     if ( entry->ipaddr != 0)  {
  322.     ipaddr= htonl( entry->ipaddr);
  323. /*        fprintf( stderr, "%u.%u.%u.%u", (ipaddr&0xff000000)>>24,
  324.         (ipaddr&0xff0000)>>16, (ipaddr&0xff00)>>8, ipaddr&0xff);
  325. */
  326.     ent= gethostbyaddr( (char*)&ipaddr, sizeof(unsigned long), AF_INET);
  327.     }
  328.     else if ( entry->hostname[0] != NULL)  {
  329. /*         fprintf( stderr, "%s", entry->hostname[0]);
  330. */
  331.     ent= gethostbyname( entry->hostname[0]);
  332.     if ( ent != NULL)  {
  333.         memcpy( &ipaddr, ent->h_addr_list[0], sizeof(ipaddr));
  334.         ipaddr= ntohl( ipaddr);
  335.         if ( (tmp= find_entry( ipaddr)) != NULL)  {
  336.         add_hostname( tmp, entry->hostname[0]);
  337.         free_entry( entry);
  338.         entry= tmp;
  339.         }
  340.         else
  341.         entry->ipaddr= ipaddr;
  342.     }
  343.     }
  344.     else
  345.     return NULL;
  346.  
  347.     if ( ent == NULL)
  348.     return NULL;
  349.  
  350.     if ( ent->h_name && ent->h_name[0] != '\0')
  351.     add_hostname( entry, ent->h_name);
  352.     alias= ent->h_aliases;
  353.     while ( *alias)  {
  354.     add_hostname( entry, *alias);
  355.     alias++;
  356.     }
  357.     return entry;
  358. }
  359.  
  360. unsigned long
  361. hcache_lookup_hostname( char *hostname)
  362. {
  363.     cache_entry *entry;
  364.     int e, h;
  365. if ( debug) printf( "looking up %s\n", hostname);
  366.     for ( e= 0; e < n_entry; e++)  {
  367.     for ( h= 0; h < 5; h++)  {
  368.         if ( hcache[e].hostname[h] &&
  369.             strcmp( hostname, hcache[e].hostname[h]) == 0)
  370.         return hcache[e].ipaddr;
  371.     }
  372.     }
  373.     entry= init_entry( 0, hostname, NULL);
  374.     if ( entry->ipaddr == 0)  {
  375. if ( debug) printf( "validating %s\n", hostname);
  376.     entry= validate_entry( entry);
  377.     n_changes++;
  378.     }
  379. if ( debug) printf( "returning %x\n", entry->ipaddr);
  380.     if ( entry != NULL && entry->ipaddr)
  381.     return entry->ipaddr;
  382.     return INADDR_NONE;
  383. }
  384.  
  385. char *
  386. hcache_lookup_ipaddr( unsigned long ipaddr)
  387. {
  388.     cache_entry *entry;
  389.     int e;
  390.     for ( e= 0; e < n_entry; e++)
  391.     if ( hcache[e].ipaddr == ipaddr)
  392.         return hcache[e].hostname[0];
  393.     entry= init_entry( ipaddr, 0, NULL);
  394. if ( debug) printf( "validating %x\n", ipaddr);
  395.     validate_entry( entry);
  396.     n_changes++;
  397.     return entry ? entry->hostname[0] : NULL;
  398. }
  399.  
  400. STATIC cache_entry *
  401. find_entry( unsigned long ipaddr)
  402. {
  403.     int e;
  404.     for ( e= 0; e < n_entry; e++)
  405.     if ( hcache[e].ipaddr == ipaddr)
  406.         return &hcache[e];
  407.     return NULL;
  408. }
  409.  
  410. STATIC void
  411. free_entry(  cache_entry *entry)
  412. {
  413.     int h;
  414.     for ( h= 0; h < 5; h++)
  415.     if ( entry->hostname[h] != NULL)
  416.         free( entry->hostname[h]);
  417.     memset( entry, 0, sizeof(*entry));
  418. }
  419.  
  420. STATIC void
  421. add_hostname( cache_entry *entry, const char *hostname)
  422. {
  423.     int h;
  424.     for ( h= 0; h < 5; h++)  {
  425.     if ( entry->hostname[h] == NULL)
  426.         break;
  427.     if ( strcmp( entry->hostname[h], hostname) == 0)
  428.         return;
  429.     }
  430.     if ( h < 5)
  431.     entry->hostname[h]= strdup( hostname);
  432. }
  433.  
  434. /*
  435. main(int argc, char *argv[])
  436. {
  437.     hcache_open( argv[1], 0);
  438.     hcache_write(NULL);
  439.  
  440.     hcache_invalidate();
  441. printf( "invalidate\n");
  442.     hcache_write(NULL);
  443.     hcache_validate();
  444. printf( "validate\n");
  445.     hcache_write( "/tmp/qhcache.out");
  446. }
  447.  
  448. */
  449.